package com.itlong.cloud.service.impl;

import com.itlong.cloud.POJO.DTO.common.ParkingMessageDTO;
import com.itlong.cloud.enumerate.ParkingBusinessOrderEnum;
import com.itlong.cloud.network.tcp.netty.ChannelPoolManage;
import com.itlong.cloud.network.tcp.netty.ServerStringHandler;
import com.itlong.cloud.service.INettyService;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.utils.node.JsonUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
 * <desc>
 *      暴露操作netty通道接口实现类
 * </desc>
 *
 * @createDate 2017/12/07
 */
@Service
public class INettyServiceImpl implements INettyService {


    private static final Logger LOG = LoggerFactory.getLogger(INettyServiceImpl.class);
    @Autowired
    RedisService redisService;
    /**
     * <desc>
     *      发送查询出场记录指令
     * </desc>
     *
     * @param clientKey     客户端的唯一标识KEY
     * @param content       参数(JSON格式)
     * @param parkingBusinessOrderEnum   出入场类型
     * @param messageId     消息唯一ID（传入20位以内唯一ID即可）
     * @return      同步返回客户端的数据
     * @author Wenchao.L
     * @createDate 2018/11/7
     */
    @Override
    public ParkingMessageDTO sendQueryInOrOutRecord(String clientKey, String content,
                            ParkingBusinessOrderEnum parkingBusinessOrderEnum,String messageId) throws IOException{
        ParkingMessageDTO message = new ParkingMessageDTO(clientKey,content,
                parkingBusinessOrderEnum.getType(),messageId);
        String result = JsonUtil.toJSON(message);
        Channel channel = ChannelPoolManage.get(clientKey);
        // 获取锁
        Lock lock = ChannelPoolManage.getChannelLock(clientKey);
        try{
            if(channel != null){
                lock.lock();
                //判断通道是否打开
                if (channel.isOpen()){
                    CountDownLatch latch = new CountDownLatch(1);
                    ServerStringHandler serverStringHandler = (ServerStringHandler) channel.pipeline().get("handler");
                    serverStringHandler.resetSync(latch,1);
                    //messageId随机生成传进来
                    serverStringHandler.setUnidId(messageId);
                    channel.writeAndFlush(Unpooled.
                            copiedBuffer((result+"\001").getBytes()));
                    //同步返回结果
                    if (latch.await(20, TimeUnit.SECONDS)){
                        Long time = 60L;
                        String text = serverStringHandler.getParkingMessageDTO().getContent();
                        if(StringUtils.isNotBlank(text)) {
                            Map<String, Object> map = JsonUtil.JsonToMap(text);
                            if (map.get("messageId") != null) {
                                redisService.set(map.get("messageId").toString(), time, serverStringHandler.getParkingMessageDTO());
                            }
                            LOG.info("【停车场交互结果返回】:"+JsonUtil.toJSON(serverStringHandler.getParkingMessageDTO()));
                            LOG.info("【停车场交互结果返回text入参messageId】:"+map.get("messageId").toString());
                        }
                        // printerServerHandler.setTimeout(0);
                        return serverStringHandler.getParkingMessageDTO();
                    }else{
                        LOG.info("【公共服务commons_netty服务端_sendQueryInOrOutRecord()】: 请求超时");
                    }
                }else{
                    LOG.info("【公共服务commons_netty服务端_sendQueryInOrOutRecord()】: 客户端通道已关闭");
                }
            }else{
                LOG.info("【公共服务commons_netty服务端_sendQueryInOrOutRecord()】: 通道不存在" + "{" + clientKey + "}");
            }
        }catch (Exception ex){
            LOG.info("【公共服务commons_netty服务端_sendQueryInOrOutRecord()】: netty主动发送消息失败",ex);
        } finally {
            if (lock != null){
                lock.unlock();
            }
        }
        return null;
    }



}
